package com.example.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.domain.dto.UserDTO;
import com.example.domain.po.User;
import com.example.exception.CustomException;
import com.example.mapper.UserMapper;
import com.example.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.example.common.enums.ResultCodeEnum.*;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;


    @Override
    public Map<String, Object> login(UserDTO userDTO) {
        User loginUser=userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,userDTO.getUsername()));
        //检查账号是否被封禁
        StpUtil.checkDisable(loginUser.getId());
        Map<String,Object> userInfo=new HashMap<>();
        if (ObjectUtil.isEmpty(loginUser)){
            throw new CustomException(USER_NOT_EXIST_ERROR);
        }
        // 使用checkpw方法检查被加密的字符串是否与原始字符串匹配：
        boolean checkpw = BCrypt.checkpw(userDTO.getPassword(),loginUser.getPassword());
        if (!checkpw){
            throw new CustomException(USER_ACCOUNT_ERROR);
        }
        //将密码设置为null返回前端
        UserDTO loginUserDTO=new UserDTO();
        BeanUtils.copyProperties(loginUser,loginUserDTO);
        loginUserDTO.setPassword(null);
        // 先登录
        StpUtil.login(loginUser.getId());
        //获取用户操作权限
        List<String> permissions = userMapper.selectUserPermission(loginUser.getId());
        //获取用户角色列表
        List<String> roles=userMapper.selectUserRoles(loginUser.getId());
        // 获取 Token  相关参数
        SaTokenInfo tokenInfo= StpUtil.getTokenInfo();
        userInfo.put("loginUser",loginUserDTO);
        userInfo.put("tokenInfo",tokenInfo);
        userInfo.put("permissions",permissions);
        userInfo.put("roles",roles);
        return userInfo;
    }

    @Override
    public List<UserDTO> getOnlineUsers() {
        // 获取所有已登录的会话id
        List<String> sessionIdList = StpUtil.searchSessionId("", 0, -1, false);
        List<UserDTO> loginUsers=new ArrayList<>();
        for (String sessionId : sessionIdList) {
            String[] parts = sessionId.split(":");
            String loginUserId = parts[3]; // 获取第四个部分
            User loginUser=userMapper.selectById(Long.valueOf(loginUserId));
            UserDTO userDTO=new UserDTO();
            // 根据会话id，查询对应的 SaSession 对象，此处一个 SaSession 对象即代表一个登录的账号
            SaSession session = StpUtil.getSessionBySessionId(sessionId);
            // 查询这个账号都在哪些设备登录了，依据上面的示例，账号A 的 tokenSign 数量是 3，账号B 的 tokenSign 数量是 2
            List<TokenSign> tokenSignList = session.getTokenSignList();
            System.out.println("会话id：" + sessionId + "，共在 " + tokenSignList.size() + " 设备登录");
            if (ObjectUtil.isNotEmpty(loginUser)){
                BeanUtils.copyProperties(loginUser,userDTO);
                userDTO.setDevices(tokenSignList.size());
                loginUsers.add(userDTO);
            }
        }
        return loginUsers;
    }

    @Override
    public void register(UserDTO userDTO) {
        System.out.println("userDTO:"+userDTO);
        User checkRegisterUser=userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername,userDTO.getUsername()));
        if (ObjectUtil.isNotEmpty(checkRegisterUser)){
            throw new CustomException(USER_EXIST_ERROR);
        }
        User registerUser=new User();
        String new_pwd = BCrypt.hashpw(userDTO.getPassword(), BCrypt.gensalt());
        BeanUtils.copyProperties(userDTO,registerUser);
        registerUser.setPassword(new_pwd);
        userMapper.insert(registerUser);

    }
}
